<?php

class UvmPredefRelations
{
    
    
    
    public function render()
    {
        return $this->_begin().$this->_relations().$this->_end();
    }
    
    private function _relations()
    {
        $model = new UvmModel('mapping');
        $data = $model->fetchRelations();
        if (is_array($data) && !empty($data)) {
            $out = array();
            foreach ($data as $row) {
                $out[] = '"'.$row['xpath'].'": "'.$row['value'].'"';
            }
            return join(",", $out).',';
        }
        return '';
    }
    
    private function _begin()
    {
        return '
/**
 * It\'s a skeleton of the pre-defs
 * this class needs more muscles and linking with back-end
 */
function UvmPredefRelations() {
    
    /**
     * Indicates if object was populated from API feed
     * 
     * @var boolean
     */
    this.wired = false;
    
    /**
     * URL
     * 
     * @var string
     */
    this.feed = \'/api.be/relations.json?refresh=1\';
    
    /**
     * Flag indicating if feed got pulled already
     * 
     * @var bool
     */
    this.feed_called = false;
    
    /**
     * Reg key for data
     * 
     * @var string
     */
    this.reg_data = \'apiFeedUvmPredefRelations\';
    
    
    /**
     * Flag indicating that the xpath was normalized and reconciled
     * This is to do with semi-inheritance (Strains)
     * 
     * @bool
     */
    this.rex = false;
    
    /**
     * Holds mappings xpath => value
     * 
     * @object hash
     */
    this.xpaths = {
       ';
    }
    
    private function _end()
    {
        return '
       "placeholder": "S"              // left to not forget trailing , (comma)
    }; // now serverd by api
    
    /**
     * Lookup structure shortlisting collections 
     * based on row a1235 
     */
    this.row2xpath = {};  
    this.calculated = false;
    
    
    /**
     * Populates .row2xpath based on existing predef data
     *
     * @return void
     */
    this.calculateRowToXpath = function() {
        var $path, $str, $exp, $section, $validator; 
        
        $validator = new UvmValidate();
        
        for ($path in this.xpaths) {
            $str = new String($path);
            $exp = $str.split(\'@\');
            $section = (new String($exp[1])).valueOf();
            
            if (false===$validator.isObject(this.row2xpath[$section])) {
                this.row2xpath[$section] = {};
            }
            this.row2xpath[$section][$path] = true;
            
            /**
             *
            if (false===$validator.isObject(this.row2xpath[$section])) {
                this.row2xpath[$section] = new Array();
            }
            this.row2xpath[$section].push($path);
            */
        }
    }
    
    /**
     * Returns value if defined, otherwise
     * 
     * @param $xpath string
     * 
     * @return string|null
     */
    this.fetchByXpath = function($xpath) {
        this.initialize(); // internally it does not reload feed if wired already
        //console.log(\'xpath: \'+$xpath);
        //console.log(\'value: \'+this.xpaths[$xpath]);
        //console.log(\'data:\');
        //console.log(this.xpaths);
        var $value = (this.xpaths[$xpath]==null) ? null : this.xpaths[$xpath];
        return $value;
    }
    
    /**
     * Sets this.xpaths
     * 
     * @param $data object Hash xpath=>value
     * 
     * @return void
     */
    this.populate = function($data) {
        //this.xpaths = $data;
    }
    
    /**
     * Appends passed hash to UvmPredefRelations.xpaths#
     * Will nicely blend with new entry point for relations
     * 
     * @param $data object Hash xpath => value
     * 
     * @param $overwrite bool If true then it would overload existing keys
     *
     * @return void
     */
    this.append = function($data, $overwrite) {
        $overwrite = ($overwrite!=true && $overwrite!=false) ? true : $overwrite; // overwrite by default
        var $validator = new UvmValidate();
        var $is_obj = $validator.isObject($data);
        if (false==$is_obj) {
            return; // no need to do anything
        }
        var $key, $value;
        for ($key in $data) {
            $value = $data[$key];
            if (null==this.xpaths[$key]) {
                this.xpaths[$key] = $value;
            } else if (null!=this.xpaths[$key] && $overwrite==true) {
                this.xpaths[$key] = $value;
            }
        }
    }
    
    /**
     * Called only once to populate from API feed
     *
     * @return bool Op status
     */
    this.initialize = function() {
        if (this.wired==false) {
            this.append(this.apiFeed(), true);
            this.wired = true;
        }
        if (this.rex==false) {
            //alert(\'Called\');
            this.normalize();
        }
        if (false==this.calculated) {
            this.calculateRowToXpath();
            this.calculated = true;
        }
        return this.wired;
    }
    
    /**
     * This is quite expensive, but it\'s only one off call
     *
     * @return void
     */
    this.normalize = function() {
        return;
        //console.log(\'One of reconciliation\');
        var $xpath, $value, $bloodline, $out = {};
        var $debug = new Array();
        //$debug.push(\'// Strain\'+"\t"+\'Original\');
        for ($xpath in this.xpaths) {
            $bloodline = (new UvmBloodline()).reset();
            $bloodline.setString($xpath);
            $out[$bloodline.getStrain()] = this.xpaths[$xpath];
            //$debug.push(\'        "\'+$bloodline.getStrain()+\'": "\'+this.xpaths[$xpath]+\'",\');
        }
        //$debug.push(\'// End\');
            
        //console.log("\n"+$debug.join("\n")+"\n");
        this.xpaths = {};
        this.xpaths = $out;
        return;
    }
    
    
    /**
     * Wraps API pull transaction (eventually connecting to back-end)
     *
     * @return Object
     */
    this.apiFeed = function() {
         return {
            "p1://a170/a92@a173": "S",      // standard - see details below tthe class
            "p1://a170/a92@a174": "O",      // optional - see details below tthe class 
            "p1://a170/a92@a175": "N/A",    // not available - see details below tthe class 
            "p1://a170/a92/a218@a175": "O" // turns optional in the context of a218 - see details below tthe class 
        }; // @todo: Link with API after integration of 14th Dec
        /**
         *
         return Reg.instance().get(this.reg_data);
        */
    }
    
    /**
     * Must be called after constructor, populates relations
     * 
     * @return void|object
     */
    this.pullFeed = function() {
        var $jqxhr = $.ajax({ 
            \'url\'      : this.feed,
            \'settings\' : {
                \'timeout\' : 12000
            }
        }).done(function() { 
            
        }).fail(function() { 
            //console.log(\'XHR query broke\');
        }).always(function($data) { 
            /*** beacuse of scope issues we need to use this pattern below ***/
            Reg.instance().set(this.reg_data, $data.result, true);
            return;
        });
        return $jqxhr;         
    }
    
    
}
';
    }
    
    
    
}
